package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ruoyi.common.config.MinIoStorageProperty;
import com.ruoyi.common.config.WlysApiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.page.PageQuery;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtil;
import com.ruoyi.common.utils.MinioTemplate;
import com.ruoyi.common.utils.RestTemplateClient;
import com.ruoyi.system.domain.MaterialLogEntity;
import com.ruoyi.system.domain.vo.MaterialsOriginalRecordVO;
import com.ruoyi.system.domain.vo.MaterialsOriginalVO;
import com.ruoyi.system.domain.vo.WlysOriginalResponse;
import com.ruoyi.system.service.MaterialLogService;
import com.ruoyi.system.service.MaterialSyncService;
import lombok.var;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;


@Service
public class MaterialSyncServiceImpl implements MaterialSyncService {

    @Autowired
    private RedisCache redisCache;


    @Autowired
    private MaterialLogService materialLogService;

    @Autowired
    private WlysApiConfig wlysApiConfig;


    @Resource
    private MinIoStorageProperty minIoStorageProperty;

    private static final Logger logger = LoggerFactory.getLogger(MaterialSyncServiceImpl.class);


    private static final String ORIGINAL_SYNC_BLOCK = "original_sync_block:";
    private static final String ORIGINAL_SYNC = "original_sync:";

    private static final String OrgId = "CRCC1101GL0220240002"; // todo 后续放到配置中


    private static final List<Integer> materialAcceptCodeList = Arrays.asList(1,2,3,4);
    @Autowired
    private MinioTemplate minioTemplate;


    // 5 分钟一次同步前 上一次同步时间之前的5 分钟的数据
    // 如果同步key 不存在 直接同步 一个月内的数据
    public void syncByProject(){
        logger.info(" 物料验收单据 --> 同步开始！");
        try {
            String nowTime = DateUtil.dateToString(new Date(),"yyyy-MM-dd HH:mm:ss");

            //查询上次更新时间
            String syncKey = ORIGINAL_SYNC; // 暂时写死
            String syncTimeFormat = redisCache.getCacheObject(syncKey);


            if (syncTimeFormat == null) {
                syncTimeFormat = DateUtil.getPreviousMonthByTimeFormat(nowTime);
            }

            String syncBeginTimeFormat = syncTimeFormat;

            if (syncTimeFormat != null) {
                syncBeginTimeFormat = subSomeTime(syncTimeFormat,  24 * 60);
            }


            executeSyncJob(syncBeginTimeFormat);
            // 同步后将 当前时间写入到 缓存中
            redisCache.setCacheObject(syncKey, nowTime);
            redisCache.expire(syncKey, 24, TimeUnit.HOURS);

            logger.info(" 物料验收单据 --> 同步结束！ now_time_format:{}  from_cache_sync_time_format:{}, set_cache_sync_time:{}",
                    nowTime, syncTimeFormat, nowTime);
        }catch (Exception e){
            logger.error("同步失败: {}", e.getMessage());
        }finally {

        }

    }

    private String subSomeTime(String nowTimeFormat, Integer numMinute ) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        LocalDateTime dateTime = LocalDateTime.parse(nowTimeFormat, formatter);

        // 减去5分钟
        LocalDateTime dateTimeMinusFiveMinutes = dateTime.minusMinutes(numMinute);

        // 如果需要将结果转换回字符串
        return dateTimeMinusFiveMinutes.format(formatter);
    }

    // 循环获取数据 按照页数 爬取最新一段时间的数据
    private void executeSyncJob(String syncBeginTimeFormat){
        int pageNo = 1,pages = 2;
        PageQuery page = new PageQuery();
        page.setPageNo(pageNo);
        page.setPageSize(200);

        while(pages >= pageNo){
            WlysOriginalResponse result = getAllAuditBill(syncBeginTimeFormat, OrgId, page);
            if(CollectionUtils.isEmpty(result.getData().getRecords())){
                return;
            }

            var materialLogRecords = result.getData().getRecords(); // 拿到记录

            // 调用入库 函数
            materialLogRecords.forEach(materialsOriginalVO -> {



                List<MaterialLogEntity> materialLogEntities = convertToMaterialLogEntity(materialsOriginalVO);
                // 插入数据

                for(var materialLogEntity : materialLogEntities) {


                    if (materialLogEntity.getMaterialCode() != null && !materialLogEntity.getMaterialCode().contains("MC01")) {
                            continue;
                    }

                    materialLogService.addMaterialLog(materialLogEntity);
                }
            });

            pages = result.getData().getPages();

            pageNo++;
            page.setPageNo(pageNo);


            try {
                // 使当前线程暂停执行2000毫秒（2秒）
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // 如果线程在睡眠期间被中断，则捕获 InterruptedException 异常
                System.out.println("Thread was interrupted.");
            }
        }

    }


    public List<MaterialLogEntity> convertToMaterialLogEntity(MaterialsOriginalVO materialsOriginalVO) {

        var ans = new ArrayList<MaterialLogEntity>();

        if (materialsOriginalVO.getRecords() == null) {
            return ans;
        }


        var newUrls = saveDownloadUrl(materialsOriginalVO);

        var imageUrls = Strings.join(newUrls, ',');

        for(var record : materialsOriginalVO.getRecords()) {
            var tmpAns = new MaterialLogEntity();
            BeanUtil.copyProperties(materialsOriginalVO, tmpAns);
            BeanUtil.copyProperties(record, tmpAns);

            // 只同步入库记录, 出库记录自己添加
            if ( !checkIn(materialsOriginalVO)) {
                 continue;
            }

            tmpAns.setIsIn(1);

            tmpAns.setMaterialMan(materialsOriginalVO.getMaterialman());

            if (materialsOriginalVO.getContractName() != null && tmpAns.getContractName() == null) {
                tmpAns.setContractName(materialsOriginalVO.getContractName());
            }

            tmpAns.setMaterialCode(materialsOriginalVO.getCode());
            tmpAns.setMaterialCode(record.getMaterialCode());

            //
            tmpAns.setSyncId(record.getId()); // 设置同步 id
            tmpAns.setId(null); // 清空 id 字段

            if (tmpAns.getDocumentTime() == null) {
                tmpAns.setDocumentTime(DateUtil.dateToString(new Date(), DatePattern.NORM_DATETIME_PATTERN));
            }
            tmpAns.setImageLink(imageUrls);

            // 下载每一张进场图片 并 上传到自己的 minio 中并 生成下载链接 放到 对应的字段中

            ans.add(tmpAns);
        }

        return ans;
    }



    public List<String> saveDownloadUrl(MaterialsOriginalVO materialsOriginalVO) {
            var ans = new ArrayList<String>();

            var filterType = new HashMap<Integer, String>();
            filterType.put(1, "1");
            filterType.put(2, "2");
            filterType.put(3, "3");
            filterType.put(4, "4");
            filterType.put(5, "5");
            filterType.put(6, "6");
            filterType.put(7, "7");
            filterType.put(8, "8");
            filterType.put(21, "21");

            for (var item : materialsOriginalVO.getAccessorys()) {
                if (!filterType.containsKey(item.getType())) {
                    continue;
                }
                var downLoadImageUrl = item.getAccessory();

                String newUrl = getCacheDownloadUrl(downLoadImageUrl);

                if (!Objects.equals(newUrl, "")) {
                    ans.add(newUrl);
                }
            }

            return ans;

    }



    private String getCacheDownloadUrl(String downLoadImageUrl ){

        try {

            String cacheUrl = redisCache.getCacheObject(downLoadImageUrl);
            if (cacheUrl != null && !cacheUrl.isEmpty()) {
                return cacheUrl;
            }

            var newFileName = getTmpFileName(downLoadImageUrl);

            var tmpFile = downloadImageAsMultipartFile(downLoadImageUrl, newFileName);

            var newFileUrl = minioTemplate.upload( tmpFile);

            redisCache.setCacheObject(downLoadImageUrl, newFileUrl, 7, TimeUnit.DAYS);

            //Files.delete(Paths.get(newFileName));

            return newFileUrl;
        } catch (IOException e) {
            logger.error("get file error:{}", e.getMessage());
        } catch (Exception e) {

        }
        return "";
    }



    private String getTmpFileName(String url) {
        try {
            URL fileUrl = new URL(url);
            String filePath = fileUrl.getPath();
            // 获取文件路径中的最后一部分，即文件名
            return filePath.substring(filePath.lastIndexOf('/') + 1);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            System.out.println("无效的 URL");
        }

        return "abc.jpg";
    }



    public boolean checkIn(MaterialsOriginalVO materialsOriginalVO) {


        if ( materialAcceptCodeList.contains(materialsOriginalVO.getTypeUse())) {
            return true;
        }


        if (materialsOriginalVO.getCode().contains("收")) {
            return true;
        }

        if (materialsOriginalVO.getCode().contains("出")) {
            return false;
        }

        if (materialsOriginalVO.getType().equals(1) || materialsOriginalVO.getType().equals(4) || materialsOriginalVO.getType().equals(6)) {
                return true;
        }
        return false;
    }


    public static MultipartFile downloadImageAsMultipartFile(String downLoadImageUrl, String tmpFileName) throws IOException {
        // 使用RestTemplate下载图片
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<byte[]> response = restTemplate.exchange(
                downLoadImageUrl,
                HttpMethod.GET,
                null,
                byte[].class
        );

        byte[] imageBytes = response.getBody();

        // 创建ByteArrayResource来包装下载的字节数组
        ByteArrayResource resource = new ByteArrayResource(imageBytes);

        // 使用MockMultipartFile创建MultipartFile实例
        MultipartFile multipartFile = new MockMultipartFile(
                "file", // 参数名，通常与表单中的<input type="file" name="...">对应
                tmpFileName, // 文件名
                "image/jpeg", // MIME类型，根据图片的实际类型来设置
                resource.getByteArray()
        );

        return multipartFile;
    }

    /*
    *  时间格式 2020-10-10 00:10:20
    * */
    public WlysOriginalResponse getAllAuditBill(String beginSyncTimeFormat, String orgCode, PageQuery page) {

        try {

            for (var i = 0; i < 3; i= i + 1) {
                Map<String, Object> requestParams = new HashMap<>();
                requestParams.put("currentPage",page.getPageNo());
                requestParams.put("pageSize",page.getPageSize());
                if(null != beginSyncTimeFormat){
                    requestParams.put("syncTime",beginSyncTimeFormat);
                }
                requestParams.put("orgCode",orgCode);
                WlysOriginalResponse result = RestTemplateClient.get(WlysOriginalResponse.class,wlysApiConfig.getApi() + wlysApiConfig.getRecord() ,requestParams);
                if(Objects.isNull(result) || result.getCode()!=200){ // 网络获取错误
                    continue;
                }
                return result;
            }

        } catch (Exception e) {
            logger.error("获取数据异常: {}", e.getMessage());
            return null;
        }

        return null;

    }


    @Override
    public List<MaterialLogEntity> getAllMaterialLogRecord(String beginSyncTimeFormat, String orgCode, PageQuery page) {


        var ans = new ArrayList<MaterialLogEntity>();

        var wlysOriginalResponse = getAllAuditBill(beginSyncTimeFormat, orgCode, page);

        if(CollectionUtils.isEmpty(wlysOriginalResponse.getData().getRecords())){
            return ans;
        }

        var materialLogRecords = wlysOriginalResponse.getData().getRecords(); // 拿到记录

        // 调用入库 函数
        materialLogRecords.forEach(materialsOriginalVO -> {
            List<MaterialLogEntity> materialLogEntities = convertToMaterialLogEntity(materialsOriginalVO);
            // 插入数据
            ans.addAll(materialLogEntities);

        });

        return ans;
    }


    public boolean getAllMaterialSave2Tab(String beginSyncTimeFormat, String orgCode, PageQuery page) {
        var materialLogRecords = getAllMaterialLogRecord(beginSyncTimeFormat, orgCode, page);
        for(var materialLogEntity : materialLogRecords) {
            materialLogService.addMaterialLog(materialLogEntity);
        }
        return true;
    }



}
